
import 'package:im_app/im/pojo/ImPojo.dart';
import 'package:json_annotation/json_annotation.dart';

import '../../../util/DateUtil.dart';
import '../base/Req.dart';

part 'Message.g.dart';

@JsonSerializable()
class MessageObject<T> extends Req {

	MessageType messageType;       // 消息类型
	String fromUserId;             // 消息发送者
	String? serverId;
	String content;
	@JsonKey(includeToJson: false)
	Object? bean;
	String? groupCode;
	String? toUserId;
	String? sessionId;

	MessageRefType? refType;
	String? refMessageIds;

	MessageStatus? status;
	MessageFileStatus? fileStatus;
	MessageActionStatus? actionStatus;
	Set<MessageUserSendInfo>? userSendInfoSet;

	MessageObject.simple(this.fromUserId, this.content, this.messageType);

	MessageObject(this.fromUserId, this.content, this.messageType);

	factory MessageObject.fromJson(Map<String, dynamic> json) => _$MessageObjectFromJson(json);

	Map<String, dynamic> toJson() => _$MessageObjectToJson(this);

	bool isGroup() {
		return this.groupCode != null;
	}

	bool isP2p() {
		return this.fromUserId != null && this.toUserId != null;
	}

	bool isRef() {
		return this.refMessageIds != null;
	}
}

class MessageObjectsReq extends Req {
	List<MessageObject> messageObjects;

	MessageObjectsReq({required this.messageObjects});

	factory MessageObjectsReq.fromJson(Map<String, dynamic> json) => _$MessageObjectsReqFromJson(json);

	Map<String, dynamic> toJson() => _$MessageObjectsReqToJson(this);
}

class RefMessageObject<T> extends MessageObject<T> {
	bool isRefRoot = false;

	RefMessageObject(MessageObject messageObject) : super(messageObject.fromUserId, messageObject.content,
			messageObject.messageType) {
		this.localSeq = messageObject.localSeq;
		this.toUserId = messageObject.toUserId;
		this.groupCode = messageObject.groupCode;
		this.fileStatus = messageObject.fileStatus;
		this.actionStatus = messageObject.actionStatus;
		this.status = messageObject.status;
		this.bean = messageObject.bean;
		this.userSendInfoSet = messageObject.userSendInfoSet;
		this.refType = messageObject.refType;
		this.refMessageIds = messageObject.refMessageIds;
		this.serverId = messageObject.serverId;
		this.createDateTime = messageObject.createDateTime;

		this.isRefRoot = true;
	}
}

@JsonSerializable()
class MessageUserSendInfo {
	String userId;
	MessageStatus? status;
	MessageActionStatus? actionStatus;
	MessageFileStatus? fileStatus;

	MessageUserSendInfo({required this.userId, this.status, this.actionStatus, this.fileStatus});

	factory MessageUserSendInfo.fromJson(Map<String, dynamic> json) => _$MessageUserSendInfoFromJson(json);

	Map<String, dynamic> toJson() => _$MessageUserSendInfoToJson(this);
}

enum MessageType {
	Text,
	Image,
	Web,
	File,
	Html,
	Video,
	RichText,
	Audio,
	Url,
	Chat,
	Group,
	;

	static MessageType ofName(String name) {
		 return MessageType.values.firstWhere((element) => element.name == name);
	 }
}

enum MessageStatus {
	none(0, "初始化"),           // 初始状态
	receive(1, "已接收"),
	readed(2, "已阅读"),         // 被取消
	withdrawed(3, "已撤回"),     // 失败
	delete(4, "删除"),           // 消息在接受中， 发送文件，图片等才有这种状态
	updated(5, "已更新"),
	;

	final int value;
	final String desc;

	const MessageStatus(this.value, this.desc);

	static MessageStatus ofName(int value) {
		return MessageStatus.values.firstWhere((element) => element.value == value);
	}
}

enum MessageFileStatus {
	none(0, "初始化"),          // 初始状态
	uploaded(1, "已上传"),      // 被取消
	downloading(2, "接受中"),   // 失败
	downloaded(3, "已下载"),    // 消息在接受中， 发送文件，图片等才有这种状态
	;

	final int value;
	final String desc;

	const MessageFileStatus(this.value, this.desc);

	static MessageFileStatus ofName(int value) {
		return MessageFileStatus.values.firstWhere((element) => element.value == value);
	}
}

enum MessageActionStatus {
	none(0, "初始化"),           // 初始状态
	readed(1, "已阅读"),         // 被取消
	withdrawed(2, "已撤回"),     //
	delete(3, "删除"),
	updated(4, "已更新"),        //
	userDelete(5, "用户删除"),   // 用户删除
	;

	final int value;
	final String desc;

	const MessageActionStatus(this.value, this.desc);

	static MessageActionStatus ofName(int value) {
		return MessageActionStatus.values.firstWhere((element) => element.value == value);
	}
}

enum MessageRefType {
	ref(1, "引用"),
	transfer(2, "转发"),
	;

	final int value;
	final String desc;

	const MessageRefType(this.value, this.desc);

	static MessageRefType ofName(String name) {
		return MessageRefType.values.firstWhere((element) => element.name == name);
	}
}